﻿//  --------------------------------
//  Copyright (c) AW Systems, Inc. All rights reserved.
//  This source code is made available under the terms of the Microsoft Public License (Ms-PL)
//  http://www.codeplex.com/SLAM/license
//  ---------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Web;
using AWS.SLAM.Configuration;
using AWS.SLAM.Logging;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace AWS.SLAM.SharePoint
{
	public class SharePointServices
	{
		#region Private State
		
		private ILogger _logger;
		private int _sequenceNumber;

		#endregion

		#region Constructors

		public SharePointServices(ILogger logger)
		{
			_logger = logger;
			_sequenceNumber = 200;
		}

		#endregion

		public void AddSlamIdFieldToContentType(string siteName, string contentTypeName)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			SPWeb rootSite = siteCollection.RootWeb;
			if (!String.IsNullOrEmpty(siteName))
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}
			else
			{
				site = rootSite;
			}

			if (site != null && site.Exists)
			{
				SPContentType contentType = null;

				try
				{
					contentType = site.ContentTypes[contentTypeName];
				}
				catch
				{
					//content type not found
				}

				if (contentType != null && !contentType.Sealed)
				{
					if (contentType.FieldLinks["SLAM_x0020_ID"] != null && !contentType.Fields.ContainsFieldWithStaticName("SLAM_x0020_ID"))
					{
						contentType.FieldLinks.Delete("SLAM_x0020_ID");

						try
						{
							site.AllowUnsafeUpdates = true;
							contentType.Update(true);
						}
						catch (Exception ex)
						{
							//SharePoint has this wonderful feature that enables us to not
							//check whether a Content Type has children.  If it does not
							//the above Update will throw an exception.  If it is does, the following
							//will not work the way we want.
							contentType.Update();
						}
					} 
					
					if (contentType.FieldLinks["SLAM_x0020_ID"] == null)
					{
						if (!rootSite.Fields.ContainsField("SLAM ID"))
						{
							rootSite.AllowUnsafeUpdates = true;

							SPField newField = rootSite.Fields.CreateNewField("SlamIdField", "SLAM ID");

							//Use reflection to set SlamIdField properties, SlamIdField
							//is in AWS.SLAM, which references AWS.SLAM.Core, so reflection
							//is necessary to avoid circular references
							Type fieldType = Type.GetType("AWS.SLAM.FieldTypes.SlamIdField, AWS.SLAM, Version=2.0.0.0, Culture=neutral, PublicKeyToken=28f8d30936a98765");
							PropertyInfo showInFormsProperty = fieldType.GetProperty("ShowInForms");
							showInFormsProperty.SetValue(newField, false, null);

							PropertyInfo generateValueProperty = fieldType.GetProperty("GenerateValue");
							generateValueProperty.SetValue(newField, true, null);

							rootSite.Fields.Add(newField);
							Thread.Sleep(800);
						}

						site.AllowUnsafeUpdates = true;
						contentType.FieldLinks.Add(new SPFieldLink(rootSite.Fields["SLAM ID"]));

						try
						{
							site.AllowUnsafeUpdates = true;
							contentType.Update(true);
						}
						catch (Exception ex)
						{
							//SharePoint has this wonderful feature that enables us to not
							//check whether a Content Type has children.  If it does not
							//the above Update will throw an exception.  If it is does, the following
							//will not work the way we want.
							contentType.Update();
						}
					}
				}
			}
		}

		public void AddSlamIdFieldToList(string siteName, string listId, string listName)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			SPWeb rootSite = siteCollection.RootWeb;
			if (!String.IsNullOrEmpty(siteName))
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}
			else
			{
				site = rootSite;
			}

			SPList list = null;

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				try
				{
					if (!String.IsNullOrEmpty(listId))
					{
						list = site.Lists[new Guid(listId)];
					}
					else
					{
						list = site.Lists[listName];
					}
				}
				catch { }

				if (list != null && !list.Fields.ContainsField("SLAM ID"))
				{
					if (!rootSite.Fields.ContainsField("SLAM ID"))
					{
						rootSite.AllowUnsafeUpdates = true;

						SPField newField = rootSite.Fields.CreateNewField("SlamIdField", "SLAM ID");

						//Use reflection to set SlamIdField properties, SlamIdField
						//is in AWS.SLAM, which references AWS.SLAM.Core, so reflection
						//is necessary to avoid circular references
						Type fieldType = Type.GetType("AWS.SLAM.FieldTypes.SlamIdField, AWS.SLAM, Version=2.0.0.0, Culture=neutral, PublicKeyToken=28f8d30936a98765");
						PropertyInfo showInFormsProperty = fieldType.GetProperty("ShowInForms");
						showInFormsProperty.SetValue(newField, false, null);

						PropertyInfo generateValueProperty = fieldType.GetProperty("GenerateValue");
						generateValueProperty.SetValue(newField, true, null);
						rootSite.Fields.Add(newField);
						Thread.Sleep(800);
					}

					if (!list.Fields.ContainsField("SLAM ID"))
					{
						SPField newField = rootSite.Fields["SLAM ID"];
						SPAddFieldOptions fieldOptions = SPAddFieldOptions.AddToAllContentTypes;
						if (!list.ContentTypesEnabled)
						{
							fieldOptions = SPAddFieldOptions.AddToDefaultContentType;
						}
						list.Fields.AddFieldAsXml(newField.SchemaXml, false, fieldOptions);
						list.Update();
					}
				}
				site.Dispose();
				rootSite.Dispose();
			}
		}

		public void RemoveSlamIdFieldToList(string siteName, string listId, string listName)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}

			SPList list = null;

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				try
				{
					if (!String.IsNullOrEmpty(listId))
					{
						list = site.Lists[new Guid(listId)];
					}
					else
					{
						list = site.Lists[listName];
					}
				}
				catch { }

				if (list != null && list.Fields.ContainsField("SLAM ID"))
				{
					SPField field = list.Fields["SLAM ID"];
					field.Hidden = false;
					field.Update();
					list.Update();

					field = list.Fields["SLAM ID"];
					field.Delete();
					list.Update();
				}

				site.Dispose();
			}
		}

		public void AttachContentTypeEventHandler(string siteName, string contentTypeName, SPEventReceiverType eventReceiverType, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				SPContentType contentType = null;

				try
				{
					contentType = site.ContentTypes[contentTypeName];
				}
				catch
				{
					//content type not found
				}

				if (contentType != null)
				{
					//verify event receiver is not duplicate
					bool exists = false;
					foreach (SPEventReceiverDefinition receiver in contentType.EventReceivers)
					{
						if (receiver.Name == "SLAM" + siteName + contentTypeName + eventReceiverType.ToString())
						{
							exists = true;
							break;
						}
					}
					if (!exists)
					{
						string receiverName = "SLAM" + siteName + contentTypeName + eventReceiverType.ToString();
						SPEventReceiverDefinition eventReceiver = contentType.EventReceivers.Add();
						eventReceiver.Name = receiverName;
						eventReceiver.Assembly = assemblyName;
						eventReceiver.Class = className;
						eventReceiver.Type = eventReceiverType;
						eventReceiver.SequenceNumber = _sequenceNumber;
						eventReceiver.Data = contentTypeName;
						eventReceiver.Update();
						contentType.Update(true, false);

						_sequenceNumber++;
					}

				}

				site.Dispose();
			}
		}

		public void AttachContentTypeEventHandlers(string siteName, string contentTypeName, SPEventReceiverType[] eventReceiverTypes, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				SPContentType contentType = null;

				try
				{
					contentType = site.ContentTypes[contentTypeName];
				}
				catch
				{
					//content type not found
				}

				if (contentType != null)
				{
					//verify event receiver is not duplicate
					bool exists = false;
					bool requiresUpdate = false;
					List<string> eventReceiversAdded = new List<string>();
					foreach (SPEventReceiverType eventReceiverType in eventReceiverTypes)
					{
						foreach (SPEventReceiverDefinition receiver in contentType.EventReceivers)
						{
							if (receiver.Name == "SLAM" + siteName + contentTypeName + eventReceiverType.ToString())
							{
								exists = true;
								break;
							}
						}

						if (!exists)
						{
							string receiverName = "SLAM" + siteName + contentTypeName + eventReceiverType.ToString();
							SPEventReceiverDefinition eventReceiver = contentType.EventReceivers.Add();
							eventReceiver.Name = receiverName;
							eventReceiver.Assembly = assemblyName;
							eventReceiver.Class = className;
							eventReceiver.Type = eventReceiverType;
							eventReceiver.SequenceNumber = _sequenceNumber;
							eventReceiver.Data = contentTypeName;
							eventReceiver.Update();
							requiresUpdate = true;
							_sequenceNumber++;
							eventReceiversAdded.Add(receiverName);
						}
						exists = false;
					}
					if (requiresUpdate)
					{
						try
						{	
							contentType.Update(true, false);

							using (SPWeb contentTypeSite = siteCollection.AllWebs[site.ID])
							{
								//Though changes were pushed to children, not all children
								//should receive updates, namely child site content types
								foreach (SPContentType siteContentType in contentTypeSite.ContentTypes)
								{
									if (siteContentType.Parent.Id.Equals(contentType.Id))
									{
										bool updateContentType = false;
										for (int i = 0; i < siteContentType.EventReceivers.Count; i++)
										{
											if (eventReceiversAdded.Contains(siteContentType.EventReceivers[i].Name))
											{
												siteContentType.EventReceivers[i].Delete();
												i--;
												updateContentType = true;
											}
										}

										if (updateContentType)
										{
											siteContentType.Update(true, false);
										}
									}
								}
							}
						}
						catch
						{
							using (SPWeb newSite = siteCollection.AllWebs[site.ID])
							{
								contentType = newSite.ContentTypes[contentTypeName];
								newSite.AllowUnsafeUpdates = true;
								contentType.Update(true, false);

								using (SPWeb contentTypeSite = siteCollection.AllWebs[site.ID])
								{
									//Though changes were pushed to children, not all children
									//should receive updates, namely child site content types
									foreach (SPContentType siteContentType in contentTypeSite.ContentTypes)
									{
										if (siteContentType.Parent.Id.Equals(contentType.Id))
										{
											bool updateContentType = false;
											for (int i = 0; i < siteContentType.EventReceivers.Count; i++)
											{
												if (eventReceiversAdded.Contains(contentType.EventReceivers[i].Name))
												{
													siteContentType.EventReceivers[i].Delete();
													i--;
													updateContentType = true;
												}
											}

											if (updateContentType)
											{
												siteContentType.Update(true, false);
											}
										}
									}
								}
							}
						}
					}
				}

				site.Dispose();
			}
		}

		public void AttachListEventHandler(string siteName, string listId, string listName, SPEventReceiverType eventReceiverType, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName) || siteName == "*")
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				try
				{
					site = siteCollection.AllWebs[siteName];
				}
				catch { }
			}

			SPList list = null;
			bool exists = false;

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				try
				{
					if (!String.IsNullOrEmpty(listId))
					{
						list = site.Lists[new Guid(listId)];
					}
					else
					{
						list = site.Lists[listName];
					}
				}
				catch { }

				if (list != null)
				{
					//verify event receiver is not duplicate
					foreach (SPEventReceiverDefinition receiver in list.EventReceivers)
					{
						if (receiver.Name == "SLAM" + siteName + listName + eventReceiverType.ToString())
						{
							exists = true;
							break;
						}
					}

					if (!exists)
					{
						SPEventReceiverDefinition eventReceiver = list.EventReceivers.Add();
						eventReceiver.Name = "SLAM" + siteName + listName + eventReceiverType.ToString();
						eventReceiver.Assembly = assemblyName;
						eventReceiver.Class = className;
						eventReceiver.Type = eventReceiverType;
						eventReceiver.SequenceNumber = _sequenceNumber;
						eventReceiver.Update();
						list.Update();

						_sequenceNumber++;
					}
				}
				site.Dispose();
			}

			if (siteName == "*")
			{
				foreach (SPWeb nextWeb in site.Site.AllWebs)
				{
					try
					{
						list = null;
						list = nextWeb.Lists[listName];

						//verify event receiver is not duplicate
						exists = false;
						foreach (SPEventReceiverDefinition receiver in list.EventReceivers)
						{
							if (receiver.Name == "SLAM" + siteName + listName + eventReceiverType.ToString())
							{
								exists = true;
								break;
							}
						}
						if (!exists)
						{
							site.AllowUnsafeUpdates = true;

							SPEventReceiverDefinition eventReceiver = list.EventReceivers.Add();
							eventReceiver.Name = "SLAM" + siteName + listName + eventReceiverType.ToString();
							eventReceiver.Assembly = assemblyName;
							eventReceiver.Class = className;
							eventReceiver.Type = eventReceiverType;
							eventReceiver.SequenceNumber = _sequenceNumber;
							eventReceiver.Update();
							//list.EventReceivers.Add(eventReceiverType, assemblyName, className);
							list.Update();

							_sequenceNumber++;
						}
					}
					catch { }
					nextWeb.Dispose();
				}
			}
		}

		/// <summary>
		/// Creates a new ContentType with the given name and collection of fields.
		/// </summary>
		/// <param name="contentTypeName"></param>
		/// <param name="fields"></param>
		/// <returns></returns>
		public bool CreateContentType(string siteName, string contentTypeName, IEnumerable<Field> fields)
		{
			bool success = true;
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				site = siteCollection.AllWebs[siteName];
			}

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;
				try
				{

					SPContentType itemContentType = site.AvailableContentTypes["Item"];
					SPContentType newContentType = new SPContentType(itemContentType, site.ContentTypes, contentTypeName);
					newContentType.Group = "List Content Types";
					site.ContentTypes.Add(newContentType);
					site.Update();

					foreach (Field newField in fields)
					{
						if (TypeDescriptor.GetProperties(newContentType).Find(newField.Name, true) == null)
						{
							SPField addField = null;
							if (!site.Fields.ContainsField(newField.Name))
							{
								addField = site.Fields.CreateNewField(newField.SharePointType, newField.Name);
								site.Fields.Add(addField);
								site.Update();
							}

							SPFieldLink fieldLink = new SPFieldLink(site.Fields[newField.Name]);
							//fieldLink.Required = newField.Required;
							newContentType.FieldLinks.Add(fieldLink);
							newContentType.Update();
						}
					}
				}
				catch
				{
					success = false;
				}

				site.Dispose();
			}
			return success;
		}

		/// <summary>
		/// Creates a new List with the given name and collection of fields.
		/// </summary>
		/// <param name="listName"></param>
		/// <param name="fields"></param>
		/// <returns></returns>
		public bool CreateList(string siteName, string listName, IEnumerable fields)
		{
			throw new NotImplementedException();
		}

		public void DetachAllEventHandlers(string assemblyName, string listClassName, string contentTypeClassName)
		{
			TraceLevel currentTraceLevel = TraceLevel.Error;

			//Check if the logger is the default SqlLogger
			SqlLogger sqlLogger = _logger is SqlLogger ? ((SqlLogger)_logger) : null;
			//If it is, force it to log Activation's messages regardless of the
			//configured trace level
			if (sqlLogger != null)
			{
				currentTraceLevel = sqlLogger.Switch.Level;
				sqlLogger.Switch.Level = TraceLevel.Verbose;
			}

			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			foreach (SPWeb site in siteCollection.AllWebs)
			{
				site.AllowUnsafeUpdates = true;

				bool performLogMessage = false;
				
				//Detach all event handlers for content types within this site
				for (int c = 0; c < site.ContentTypes.Count; c++)
				{
					//This is a little ridiculous, but because we are using
					//contentType.Update(true, false) to propagate the event receiver deletion to
					//the children of this content type without the "innerSite" here opened for every one
					//this process will throw an exception with the message:
					//"The object has been updated by another user since it was last fetched"
					using (SPWeb innerSite = siteCollection.OpenWeb(site.ID))
					{
						SPContentType contentType = innerSite.ContentTypes[site.ContentTypes[c].Id];
						if (!contentType.Sealed && !contentType.ReadOnly)
						{
							bool updateContentType = false;
							for (int i = 0; i < contentType.EventReceivers.Count; i++)
							{
								//Check if the assembly name, at the beginning, and the PublicKeyToken, at the end
								//of the full Assembly name matches.  This should detach event handlers
								//from old versions.
								if ((contentType.EventReceivers[i].Assembly.StartsWith(assemblyName.Substring(0, assemblyName.IndexOf(",")))) ||
									contentType.EventReceivers[i].Name.StartsWith("SLAM"))
								{
									contentType.EventReceivers[i].Delete();
									i--;
									performLogMessage = true;
									updateContentType = true;
								}
							}

							if (updateContentType)
							{
								contentType.Update(true, false);
							}

							if (performLogMessage)
							{
								string typeString = "";
								if (String.IsNullOrEmpty(site.ServerRelativeUrl.TrimEnd('/')))
								{
									typeString = String.Format("{0} - {1}", site.ServerRelativeUrl.TrimEnd('/'), contentType.Name);
								}
								else
								{
									typeString = contentType.Name;
								}
								_logger.LogMessage("Information", "Detached Event Handlers for Content Type: " + typeString);
							}

							performLogMessage = false;
						}
					}
				}

				//Detach all event handlers for Lists within this site
				for (int l = 0; l < site.Lists.Count; l++)
				{
					SPList list = site.Lists[l];
					for (int i = 0; i < list.EventReceivers.Count; i++)
					{
						//Check if the assembly name, at the beginning, and the PublicKeyToken, at the end
						//of the full Assembly name matches.  This should detach event handlers
						//from old versions.
						if ((list.EventReceivers[i].Assembly.StartsWith(assemblyName.Substring(0, assemblyName.IndexOf(",")))) ||
							list.EventReceivers[i].Name.StartsWith("SLAM"))
						{
							list.EventReceivers[i].Delete();
							i--;
							performLogMessage = true;
						}
					}

					list.Update();

					if (performLogMessage)
					{
						string typeString = "";
						if (String.IsNullOrEmpty(site.ServerRelativeUrl.TrimEnd('/')))
						{
							typeString = String.Format("{0} - {1} - {2}", site.ServerRelativeUrl.TrimEnd('/'), list.ID.ToString(), list.Title);
						}
						else
						{
							typeString = String.Format("{0} - {1}", list.ID.ToString(), list.Title);
						}
						_logger.LogMessage("Information", "Detached Event Handlers for List: " + typeString);
					}

					performLogMessage = false;
				}

				site.Dispose();
			}
		}

		public void DetachContentTypeEventHandlers(string siteName, string contentTypeName, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				site = siteCollection.AllWebs[siteName];
			}

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				SPContentType contentType = site.ContentTypes[contentTypeName];

				bool updateContentType = false;
				for (int i = 0; i < contentType.EventReceivers.Count; i++)
				{
					//Check if the assembly name, at the beginning, and the PublicKeyToken, at the end
					//of the full Assembly name matches.  This should detach event handlers
					//from old versions.
					if ((contentType.EventReceivers[i].Assembly.StartsWith(assemblyName.Substring(0, assemblyName.IndexOf(",") + 1)) &&
						contentType.EventReceivers[i].Assembly.EndsWith(assemblyName.Substring(assemblyName.LastIndexOf(",") + 1)) &&
						contentType.EventReceivers[i].Class == className) ||
						contentType.EventReceivers[i].Name.StartsWith("SLAM"))
					{
						contentType.EventReceivers[i].Delete();
						i--;
						updateContentType = true;
					}
				}

				if (updateContentType)
				{
					contentType.Update(true, false);
				}
				site.Dispose();
			}
		}

		public void DetachListContentTypeEventHandlers(string siteName, string listId, string listName, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				site = siteCollection.AllWebs[siteName];
			}

			if (site != null && site.Exists)
			{
				site.AllowUnsafeUpdates = true;

				SPList list = null;
				try
				{
					if (!String.IsNullOrEmpty(listId))
					{
						list = site.Lists[new Guid(listId)];
					}
					else
					{
						list = site.Lists[listName];
					}
				}
				catch { }

				if (list != null)
				{
					foreach (SPContentType contentType in list.ContentTypes)
					{
						bool updateContentType = false;
						for (int i = 0; i < contentType.EventReceivers.Count; i++)
						{
							//Check if the assembly name, at the beginning, and the PublicKeyToken, at the end
							//of the full Assembly name matches.  This should detach event handlers
							//from old versions.
							if ((contentType.EventReceivers[i].Assembly.StartsWith(assemblyName.Substring(0, assemblyName.IndexOf(",") + 1)) &&
								contentType.EventReceivers[i].Assembly.EndsWith(assemblyName.Substring(assemblyName.LastIndexOf(",") + 1)) &&
								contentType.EventReceivers[i].Class == className) ||
								contentType.EventReceivers[i].Name.StartsWith("SLAM"))
							{
								contentType.EventReceivers[i].Delete();
								i--;
								updateContentType = true;
							}
						}

						if (updateContentType)
						{
							contentType.Update(true, false);
						}
					}

					list.Update();
				}

				site.Dispose();
			}
		}

		public void DetachListEventHandlers(string siteName, string listId, string listName, string assemblyName, string className)
		{
			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			try
			{
				if (String.IsNullOrEmpty(siteName) || siteName == "*")
				{
					site = siteCollection.RootWeb;
				}
				else
				{
					site = siteCollection.AllWebs[siteName];
				}
			}
			catch { }

			if (site != null)
			{
				SPList list = null;

				if (site.Exists)
				{
					site.AllowUnsafeUpdates = true;

					try
					{
						if (!String.IsNullOrEmpty(listId))
						{
							list = site.Lists[new Guid(listId)];
						}
						else
						{
							list = site.Lists[listName];
						}
					}
					catch { }
					if (list != null)
					{
						for (int i = 0; i < list.EventReceivers.Count; i++)
						{
							//Check if the assembly name, at the beginning, and the PublicKeyToken, at the end
							//of the full Assembly name matches.  This should detach event handlers
							//from old versions.
							if ((list.EventReceivers[i].Assembly.StartsWith(assemblyName.Substring(0, assemblyName.IndexOf(",") + 1)) &&
								list.EventReceivers[i].Assembly.EndsWith(assemblyName.Substring(assemblyName.LastIndexOf(",") + 1)) &&
								list.EventReceivers[i].Class == className) ||
								list.EventReceivers[i].Name.StartsWith("SLAM"))
							{
								list.EventReceivers[i].Delete();
								i--;
							}
						}

						list.Update();
					}



					if (siteName == "*")
					{
						foreach (SPWeb nextWeb in site.Site.AllWebs)
						{
							try
							{
								list = null;
								try
								{
									if (!String.IsNullOrEmpty(listId))
									{
										list = nextWeb.Lists[new Guid(listId)];
									}
									else
									{
										list = nextWeb.Lists[listName];
									}
								}
								catch { }
								if (list != null)
								{
									for (int i = 0; i < list.EventReceivers.Count; i++)
									{
										if (list.EventReceivers[i].Assembly == assemblyName && list.EventReceivers[i].Class == className)
										{
											list.EventReceivers[i].Delete();
											i--;
										}
									}

									list.Update();
								}
							}
							catch { }
							nextWeb.Dispose();
						}
					}

					site.Dispose();
				}
			}
		}

		public bool VerifyContentTypeExists(string siteName, string contentTypeName)
		{
			bool contentTypeExists = true;

			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				site = siteCollection.AllWebs[siteName];
			}

			try
			{
				contentTypeExists = site.ContentTypes[contentTypeName] != null;
			}
			catch
			{
				contentTypeExists = false;
			}

			site.Dispose();
			return contentTypeExists;
		}

		public bool VerifyListExists(string siteName, string listName)
		{
			bool listExists = true;

			SPSite siteCollection = SPControl.GetContextSite(HttpContext.Current);

			SPWeb site = null;
			if (String.IsNullOrEmpty(siteName))
			{
				site = siteCollection.RootWeb;
			}
			else
			{
				site = siteCollection.AllWebs[siteName];
			}

			try
			{
				listExists = site.Lists[listName] != null;
			}
			catch
			{
				listExists = false;
			}

			site.Dispose();
			return listExists;
		}
	}
}
